/*
 ------------------------------------------------------------------------------
 Copyright (C) 2013 Eternal Games.

 This file is part of the GLQuake source code.

 The GLQuake source code is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your
 option) any later version.

 The GLQuake source code is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 more details.

 You should have received a copy of the GNU General Public License along with
 the GLQuake source code; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 ------------------------------------------------------------------------------
*/


//
// protocol.h - game protocol
//


#ifndef __GAME_PROTOCOL_H__
#define __GAME_PROTOCOL_H__


#define MAX_SNAPSHOT_ENTITIES			1024

// Config strings are a general means of communicating variable length strings
// from the server to all connected clients.
// A config string can have at most MAX_STRING_LENGTH characters.
#define MAX_CONFIG_STRINGS				4096

#define CS_VERSION						0
#define CS_LEVEL_NAME					1
#define CS_GRAVITY						2
#define CS_MUSIC						3

#define CS_CLIENTS						32
#define CS_MODELS						(CS_CLIENTS + MAX_CLIENTS)
#define CS_MATERIALS					(CS_MODELS + MAX_GAME_MODELS)
#define CS_SOUND_SHADERS				(CS_MATERIALS + MAX_GAME_MATERIALS)

// A game state contains information about the current game.
// It is only transmitted to clients when they connect to the server, but some
// parts of it (such as config strings) can also be updated during gameplay.
#define GS_CONFIGSTRINGS_FIRST			0
#define GS_CONFIGSTRINGS_LAST			0 + (MAX_CONFIG_STRINGS - 1)

#define GS_BASELINES_FIRST				MAX_CONFIG_STRINGS
#define GS_BASELINES_LAST				MAX_CONFIG_STRINGS + (MAX_ENTITIES - 1)

// These must be changed if the values they depend on are changed!
#define PS_MOVE_TYPE_BITS				3		// playerState_t->pmType
#define PS_MOVE_FLAGS_BITS				10		// playerState_t->pmFlags
#define PS_MOVE_TIME_BITS				16		// playerState_t->pmTime

#define ES_NUMBER_BITS					12		// entityState->number
#define ES_TYPE_BITS					4		// entityState->type
#define ES_FLAGS_BITS					16		// entityState->flags

#define ES_BIND_MASTER_BITS				12		// entityState->bindMaster

#define ES_MODEL_BITS					9		// MAX_GAME_MODELS
#define ES_CLIP_MODEL_BITS				9		// MAX_GAME_CLIP_MODELS
#define ES_MATERIAL_BITS				9		// MAX_GAME_MATERIALS
#define ES_SOUND_SHADER_BITS			9		// MAX_GAME_SOUND_SHADERS

/*
 ==============================================================================

 WEAPONS

 ==============================================================================
*/

// TODO!!!
enum weaponType_t {
	WP_NONE,
	WP_AXE,
	WP_SHOTGUN,
	WP_SUPERSHOTGUN,
	WP_NAILGUN,
	WP_SUPERNAILGUN,
	WP_GRENADELAUNCHER,
	WP_ROCKETLAUNCHER,
	WP_LIGHTNINGUN,
	WP_MAX_TYPES
};

/*
 ==============================================================================

 EVENTS

 ==============================================================================
*/

#define MAX_EVENTS						4

// Entity events are for effects that take place relative to an existing entity
// origin. Very network efficient.
enum eventType_t {
	EV_NONE,
	EV_JUMP,
	EV_STEP,
	EV_PLAYSOUND,
	EV_STOPSOUND,
	EV_PROJECTILE,
	EV_FIRE_WEAPON,
	EV_GIB
};

/*
 ==============================================================================

 PLAYER STATE

 ==============================================================================
*/

// The playerState_t structure contains information needed by both the client
// and server to predict player motion and actions.
// This is a full superset of entityState_t as it is used by players, so if a
// playerState_t is transmitted, the entityState_t can be fully derived from
// it.
struct playerState_t {
	int						pmType;
	int						pmFlags;
	int						pmTime;

	int						clientNum;

	int						flags;

	glqVec3					origin;
	glqVec3					velocity;

	int						bounds;
	float					viewHeight;

	int						weaponType;
	int						weaponFrame;

	glqAngles				viewAngles;
	glqAngles				deltaAngles;		// Add to user command angles to get view angles

	int						userCmdTime;		// Time of last user command executed

	int						groundEntityNum;	// ENTITYNUM_NONE == in air

	// Event queue
	int						eventSequence;
	int						eventTypes[MAX_EVENTS];
	int						eventParms[MAX_EVENTS];
};

/*
 ==============================================================================

 ENTITY STATE

 ==============================================================================
*/

#define MAX_ENTITY_STATE_SIZE			256

enum entityType_t {
	ET_BAD,
	ET_GENERAL,
	ET_MOVER,
	ET_BEAM,
	ET_LIGHT,
	ET_SPEAKER,
	ET_PLAYER,
	ET_ITEM,
	ET_MONSTER,
	ET_PROJECTILE
};

enum entityFlags_t {
	EF_VIEW_MAIN			= BIT(0),			// Visible in the main view
	EF_VIEW_SKY				= BIT(1),			// Visible in a sky view
	EF_VIEW_MIRROR			= BIT(2),			// Visible in a mirror view
	EF_VIEW_PORTAL			= BIT(3),			// Visible in a portal view
	EF_VIEW_REMOTE			= BIT(4),			// Visible in a remote view
	EF_IGNORE				= BIT(5),			// Completely ignore the entity except for binding
	EF_VISIBLE				= BIT(6),			// Entity is visible
	EF_AUDIBLE				= BIT(7),			// Entity is audible
	EF_MOVEABLE				= BIT(8),			// Entity is moveable
	EF_BLOCKED				= BIT(9),			// Set when blocked by another entity
	EF_TELEPORT				= BIT(10)			// Toggled every time the origin abruptly changes
};

// The entityState_t structure contains the information conveyed from the
// server in an update message about entities that the client will need to
// render in some way.
// Different types will use the state buffer in different ways.
// The messages are delta compressed, so it doesn't really matter if the
// structure size is fairly large.
struct entityState_t {
	int						number;
	int						type;
	int						flags;

	int						weaponType;

	int						frame;

	// Position and orientation
	etTrajectory<glqVec3>	origin;
	etTrajectory<glqAngles>	angles;

	// Binding information
	int						bindMaster;
	bool					bindOrientated;

	// Event queue
	int						eventSequence;
	int						eventTypes[MAX_EVENTS];
	int						eventParms[MAX_EVENTS];

	// State buffer
	byte					buffer[MAX_ENTITY_STATE_SIZE];
};

// Structures for the different types of entities
struct general_t {
	int						contents;
	int						bounds;

	int						model;
	int						clipModel;

	int						material;
	float					materialParms[MAX_MATERIAL_PARMS];

	int						sound;
	int						soundTime;
	float					soundParms[MAX_SOUND_PARMS];
};

struct mover_t {
	int						model;
};

struct light_t {
	int						type;

	glqVec3					center;

	glqVec3					radius;

	float					xMin;
	float					xMax;

	float					yMin;
	float					yMax;

	float					zNear;
	float					zFar;

	bool					noShadows;

	float					shadowBias;
	float					shadowSlopeScaleBias;

	float					shadowSoftness;

	float					fogDistance;
	float					fogHeight;

	float					volumeIntensity;

	bool					volumeShadows;
	bool					volumeInteractions;

	int						detailLevel;

	int						material;
	float					materialParms[MAX_MATERIAL_PARMS];
};

struct speaker_t {
	glqVec3					direction;

	int						sound;
	int						soundTime;
	float					soundParms[MAX_SOUND_PARMS];
};

struct player_t {
	int						bounds;

	int						model;

	int						sound;
	int						soundTime;
	float					soundParms[MAX_SOUND_PARMS];
};

struct item_t {
	int						bounds;

	int						model;

	int						sound;
	int						soundTime;
	float					soundParms[MAX_SOUND_PARMS];
};

struct monster_t {
	int						bounds;

	int						model;
	// TODO: need the headModel for gibs

	int						sound;
	int						soundTime;
	float					soundParms[MAX_SOUND_PARMS];
};

struct projectile_t {
	int todo;
};


#endif	// __GAME_PROTOCOL_H__